package com.niiwoo.civet.trade.service.local.creditor;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.joda.time.DateTime;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.niiwoo.civet.trade.dao.entity.CreditorSaleDetail;
import com.niiwoo.civet.trade.dao.entity.CreditorSelling;
import com.niiwoo.civet.trade.dao.entity.InvestorCreditor;
import com.niiwoo.civet.trade.dao.entity.ProjectInvestOrder;
import com.niiwoo.civet.trade.dao.mapper.CreditorSaleDetailMapperExt;
import com.niiwoo.civet.trade.dao.mapper.CreditorSellingMapperExt;
import com.niiwoo.civet.trade.dao.mapper.InvestorCreditorMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectInvestOrderMapperExt;
import com.niiwoo.civet.trade.enums.InvestorCreditorStatusEnum;
import com.niiwoo.civet.trade.enums.ProjectInvestOrderEvolutionStatusEnum;
import com.niiwoo.civet.trade.enums.creditorSale.SaleDetailEndTypeEnum;
import com.niiwoo.civet.trade.enums.creditorSale.SaleDetailStatusEnum;
import com.niiwoo.tripod.lanmao.component.LanMaoDirectService;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.lanmao.enums.ResponseCodeEnum;
import com.niiwoo.tripod.lanmao.enums.ResponseStatusEnum;
import com.niiwoo.tripod.lanmao.request.CancelDebentureSaleRequest;
import com.niiwoo.tripod.lanmao.request.DebentureSaleRequest;
import com.niiwoo.tripod.lanmao.request.QueryTransactionRequest;
import com.niiwoo.tripod.lanmao.response.DebentureSaleResponse;
import com.niiwoo.tripod.lanmao.response.LanMaoResponse;
import com.niiwoo.tripod.lanmao.response.QueryDebentureSaleResponse;
import com.niiwoo.tripod.lanmao.response.QueryDebentureSaleResponse.DebentureSaleDetail;

import lombok.extern.slf4j.Slf4j;

/**
 * 债权出让调用懒猫相关操作
 *
 * @author kevin.jia
 * @create 2018年7月6日 上午9:27:59
 */
@Slf4j
@Service
public class CreditorSaleOrderToLanMaoService {

    @Autowired
    private CreditorSaleDetailMapperExt creditorSaleDetailMapperExt;
    
    @Autowired
    private InvestorCreditorMapperExt investorCreditorMapperExt;
    
    @Autowired
    private CreditorSellingMapperExt creditorSellingMapperExt;
    
    @Autowired
    private ProjectInvestOrderMapperExt projectInvestOrderMapperExt;
    
    @Autowired
    private LanMaoDirectService lanMaoDirectService;
    
    @Autowired
    private LanMaoSequence lanMaoSequence;

	/**
	 * 调用懒猫单笔债权出让
	 * 
	 * @param creditorSaleDetailList
	 */
	public void invokeLaoMaoToDebentureSale(List<CreditorSaleDetail> creditorSaleDetailList) {
		Long batchId = creditorSaleDetailList.get(0).getBatchId();
		Long beginTime = System.currentTimeMillis();
		log.info("###债权出让###批次ID:{}，详情记录数:{}", batchId, creditorSaleDetailList.size());
		for (CreditorSaleDetail creditorSaleDetail : creditorSaleDetailList) {
			try {
				// 构建调用存管请求参数
				DebentureSaleRequest request = new DebentureSaleRequest();
				request.setPlatformUserNo(creditorSaleDetail.getPlatformUserNo());
				request.setProjectNo(String.valueOf(creditorSaleDetail.getProjectId()));
				request.setRequestNo(creditorSaleDetail.getRequestNo());
				request.setSaleShare(creditorSaleDetail.getShare());
				
				log.info("###债权出让###调用懒猫调用单笔债权出让接口，ID:{},请求参数:{}", creditorSaleDetail.getId(), JSONObject.toJSONString(request));
				CompletableFuture<DebentureSaleResponse> debentureSaleResponseFuture = lanMaoDirectService.debentureSale(request);
				DebentureSaleResponse debentureSaleResponse = debentureSaleResponseFuture.get();
				log.info("###债权出让###调用懒猫调用单笔债权出让接口，ID:{},返回结果:{}", creditorSaleDetail.getId(), JSONObject.toJSONString(debentureSaleResponse));
				
				// 调用存管返回结果处理
				if (null == debentureSaleResponse || "100001".equals(debentureSaleResponse.getErrorCode())) {
					log.error("###债权出让###调用懒猫调用单笔债权出让接口系统错误，ID:{}", creditorSaleDetail.getId());
					return;
				}
				if (ResponseCodeEnum.SUCCESS.getValue().equals(debentureSaleResponse.getCode())
						&& ResponseStatusEnum.SUCCESS.getValue().equals(debentureSaleResponse.getStatus())) {
					getProxyObject().creditorSaleHandleToSuccess(creditorSaleDetail);
				} else  {
					getProxyObject().creditorSaleHandleToFailed(creditorSaleDetail, debentureSaleResponse.getErrorCode(), debentureSaleResponse.getErrorMessage());
				}
				log.info("###债权出让###调用懒猫调用单笔债权出让接口，处理完成。ID:{}", creditorSaleDetail.getId());
			} catch (Exception e) {
				log.error("###债权出让###调用懒猫调用单笔债权出让接口系统异常，ID:{}", creditorSaleDetail.getId(), e);
			}
		}
		log.info("###债权出让###批次ID:{}处理完成, 总耗时:{}ms", batchId, System.currentTimeMillis() - beginTime);
	}

	/**
	 * 单个债权补偿
	 * 
	 * @param creditorSaleDetail
	 */
	public void debentureSaleCompensation(CreditorSaleDetail creditorSaleDetail) {
		try {
			// 构建调用存管请求参数
			QueryTransactionRequest request = new QueryTransactionRequest();
			request.setPlatformUserNo(creditorSaleDetail.getPlatformUserNo());
			request.setRequestNo(creditorSaleDetail.getRequestNo());
			
			log.info("###债权出让补偿###调用懒猫查询单笔债权交易接口，ID:{},请求参数:{}", creditorSaleDetail.getId(), JSONObject.toJSONString(request));
			CompletableFuture<QueryDebentureSaleResponse> queryDebentureSaleResponseFuture = lanMaoDirectService.queryDebentureSale(request);
			QueryDebentureSaleResponse queryDebentureSaleResponse = queryDebentureSaleResponseFuture.get();
			log.info("###债权出让补偿###调用懒猫查询单笔债权交易接口，ID:{},返回结果:{}", creditorSaleDetail.getId(), JSONObject.toJSONString(queryDebentureSaleResponse));
			
			// 调用存管返回结果处理
			if (null == queryDebentureSaleResponse || "100001".equals(queryDebentureSaleResponse.getErrorCode())) {
				log.error("###债权出让补偿###调用懒猫查询单笔债权交易接口系统错误，ID:{}", creditorSaleDetail.getId());
				return;
			}
			if (ResponseCodeEnum.SUCCESS.getValue().equals(queryDebentureSaleResponse.getCode())
					&& ResponseStatusEnum.SUCCESS.getValue().equals(queryDebentureSaleResponse.getStatus())) {
				DebentureSaleDetail debentureSaleDetail = queryDebentureSaleResponse.getRecords().get(0);
				if ("ONSALE".equals(debentureSaleDetail.getStatus())) {
					getProxyObject().creditorSaleHandleToSuccess(creditorSaleDetail);
				}
			} else {
				getProxyObject().creditorSaleHandleToFailed(creditorSaleDetail, queryDebentureSaleResponse.getErrorCode(), queryDebentureSaleResponse.getErrorMessage());
			}
			log.info("###债权出让补偿###调用懒猫查询单笔债权交易接口，处理完成。ID:{}", creditorSaleDetail.getId());
		} catch (Exception e) {
			log.error("###债权出让补偿###调用懒猫查询单笔债权交易接口系统异常，ID:{}", creditorSaleDetail.getId(), e);
		}
	}
	
	/**
	 * 债权取消
	 * 
	 * @param creditorSaleDetail
	 */
	public void invokeLanMaoCancelDebentureSale(CreditorSaleDetail creditorSaleDetail) {
		try {
			CancelDebentureSaleRequest request = new CancelDebentureSaleRequest();
			request.setRequestNo(lanMaoSequence.getRequestNo());
			request.setCreditsaleRequestNo(creditorSaleDetail.getRequestNo());
			
			log.info("###取消债权出让###调用懒猫取消债权出让接口，ID:{},请求参数:{}", creditorSaleDetail.getId(), JSONObject.toJSONString(request));
			CompletableFuture<LanMaoResponse> lanMaoResponseFuture = lanMaoDirectService.cancelDebentureSale(request);
			LanMaoResponse lanMaoResponse = lanMaoResponseFuture.get();
			log.info("###取消债权出让###调用懒猫取消债权出让接口，ID:{},返回结果:{}", creditorSaleDetail.getId(), JSONObject.toJSONString(lanMaoResponse));
			
			// 返回成功更新同步状态
			if (ResponseCodeEnum.SUCCESS.getValue().equals(lanMaoResponse.getCode())
					&& ResponseStatusEnum.SUCCESS.getValue().equals(lanMaoResponse.getStatus())) {
				getProxyObject().syncCreditorSaleOrderStatusToBank(creditorSaleDetail);
			}
		} catch (Exception e) {
			log.error("###取消债权出让###调用懒猫取消债权出让接口系统异常，ID:{}", creditorSaleDetail.getId(), e);
		}
	}	
	
	/**
	 * 债权取消补偿
	 * 
	 * @param creditorSaleDetail
	 */
	public void invokeLanMaoCancelDebentureSaleCompensation(CreditorSaleDetail creditorSaleDetail) {
		try {
			QueryTransactionRequest request = new QueryTransactionRequest();
			request.setPlatformUserNo(creditorSaleDetail.getPlatformUserNo());
			request.setRequestNo(creditorSaleDetail.getRequestNo());
			log.info("###取消债权出让补偿###调用懒猫查询单笔债权交易接口，ID:{},请求参数:{}", creditorSaleDetail.getId(), JSONObject.toJSONString(request));
			CompletableFuture<QueryDebentureSaleResponse> queryDebentureSaleResponseFuture = lanMaoDirectService.queryDebentureSale(request);
			QueryDebentureSaleResponse queryDebentureSaleResponse = queryDebentureSaleResponseFuture.get();
			log.info("###取消债权出让补偿###调用懒猫查询单笔债权交易接口，ID:{},返回结果:{}", creditorSaleDetail.getId(), JSONObject.toJSONString(queryDebentureSaleResponse));
			
			// 调用存管返回结果处理
			if (null == queryDebentureSaleResponse || "100001".equals(queryDebentureSaleResponse.getErrorCode())) {
				log.error("###取消债权出让补偿###调用懒猫查询单笔债权交易接口系统错误，ID:{}", creditorSaleDetail.getId());
				return;
			}
			if (ResponseCodeEnum.SUCCESS.getValue().equals(queryDebentureSaleResponse.getCode())
					&& ResponseStatusEnum.SUCCESS.getValue().equals(queryDebentureSaleResponse.getStatus())) {
				DebentureSaleDetail debentureSaleDetail = queryDebentureSaleResponse.getRecords().get(0);
				if ("COMPLETED".equals(debentureSaleDetail.getStatus())) {
					getProxyObject().syncCreditorSaleOrderStatusToBank(creditorSaleDetail);
				} else if ("ONSALE".equals(debentureSaleDetail.getStatus())) {
					invokeLanMaoCancelDebentureSale(creditorSaleDetail);
				}
			}
		} catch (Exception e) {
			log.error("###取消债权出让补偿###调用懒猫取消债权出让接口系统异常，ID:{}", creditorSaleDetail.getId(), e);
		}
	}

	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void creditorSaleHandleToFailed(CreditorSaleDetail creditorSaleDetail, String errorCode,
			String errorMessage) {
		CreditorSaleDetail updateCreditorSaleDetail = new CreditorSaleDetail();
		updateCreditorSaleDetail.setId(creditorSaleDetail.getId());
		updateCreditorSaleDetail.setUserId(creditorSaleDetail.getUserId());
		updateCreditorSaleDetail.setStatus(SaleDetailStatusEnum.SALE_END.getValue());
		updateCreditorSaleDetail.setEndType(SaleDetailEndTypeEnum.OTHER.getValue());
		updateCreditorSaleDetail.setErrorCode(errorCode);
		updateCreditorSaleDetail.setEndMessage(errorMessage);
		updateCreditorSaleDetail.setEndTime(new Date());
		creditorSaleDetailMapperExt.updateByPrimaryKeyAndUserIdSelective(updateCreditorSaleDetail);
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void creditorSaleHandleToSuccess(CreditorSaleDetail creditorSaleDetail) {
		DateTime currentDate = new DateTime();
		
		// 更新债权出让状态
		CreditorSaleDetail updateCreditorSaleDetail = new CreditorSaleDetail();
		updateCreditorSaleDetail.setId(creditorSaleDetail.getId());
		updateCreditorSaleDetail.setUserId(creditorSaleDetail.getUserId());
		updateCreditorSaleDetail.setStatus(SaleDetailStatusEnum.SELLING.getValue());
		updateCreditorSaleDetail.setUpdateTime(currentDate.toDate());
		creditorSaleDetailMapperExt.updateByPrimaryKeyAndUserIdSelective(updateCreditorSaleDetail);
		
		// 更新投资债权为出让中
		InvestorCreditor investorCreditor = investorCreditorMapperExt.selectByInvestOrderId(creditorSaleDetail.getInvestOrderId());
		InvestorCreditor updateInvestorCreditor = new InvestorCreditor();
		updateInvestorCreditor.setId(investorCreditor.getId());
		updateInvestorCreditor.setStatus(InvestorCreditorStatusEnum.TRANSFERRING.getStatus());
		updateInvestorCreditor.setUpdateTime(currentDate.toDate());
		investorCreditorMapperExt.updateByPrimaryKeySelective(updateInvestorCreditor);
		
		// 更新投资订单为出让中
		ProjectInvestOrder updateProjectInvestOrder = new ProjectInvestOrder();
		updateProjectInvestOrder.setId(creditorSaleDetail.getInvestOrderId());
		updateProjectInvestOrder.setEvolutionStatus(ProjectInvestOrderEvolutionStatusEnum.IN_TRANSFER.getValue());
		updateProjectInvestOrder.setUpdateTime(currentDate.toDate());
		projectInvestOrderMapperExt.updateByPrimaryKeySelective(updateProjectInvestOrder);
		
		// 生成出让中的债权订单
		CreditorSelling creditorSelling = new CreditorSelling();
		creditorSelling.setCreditorSaleDetailId(creditorSaleDetail.getId());
		creditorSelling.setInvestOrderId(creditorSaleDetail.getInvestOrderId());
		creditorSelling.setProjectId(creditorSaleDetail.getProjectId());
		creditorSelling.setBorrowRate(creditorSaleDetail.getBorrowRate());
		creditorSelling.setDeadline(creditorSaleDetail.getDeadline());
		creditorSelling.setRemainingDeadlineMonth(creditorSaleDetail.getRemainingDeadlineMonth());
		creditorSelling.setRemainingDeadlineDay(creditorSaleDetail.getRemainingDeadlineDay());
		creditorSelling.setRepaymentType(creditorSaleDetail.getRepaymentType());
		creditorSelling.setBorrowerType(creditorSaleDetail.getBorrowerType());
		creditorSelling.setEndDate(creditorSaleDetail.getEndDate());
		creditorSelling.setUserId(creditorSaleDetail.getUserId());
		creditorSelling.setRealName(creditorSaleDetail.getRealName());
		creditorSelling.setHeadImage(creditorSaleDetail.getHeadImage());
		creditorSelling.setMobile(creditorSaleDetail.getMobile());
		creditorSelling.setGender(creditorSaleDetail.getGender());
		creditorSelling.setNiiwooScore(creditorSaleDetail.getNiiwooScore());
		creditorSelling.setNickName(creditorSaleDetail.getNickName());
		creditorSelling.setSaleAmount(creditorSaleDetail.getSaleAmount());
		creditorSelling.setShare(creditorSaleDetail.getShare());
		creditorSelling.setInterest(creditorSaleDetail.getInterest());
		creditorSelling.setOffPercent(creditorSaleDetail.getOffPercent());
		creditorSelling.setOffAmount(creditorSaleDetail.getOffAmount());
		creditorSelling.setCurrentInterestForDay(creditorSaleDetail.getCurrentInterestForDay());
		creditorSelling.setStatus((byte) 1);
		creditorSelling.setExpireTime(creditorSaleDetail.getExpireTime());
		creditorSelling.setCreateTime(currentDate.toDate());
		creditorSelling.setUpdateTime(currentDate.toDate());
		creditorSellingMapperExt.insertSelective(creditorSelling);
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void syncCreditorSaleOrderStatusToBank(CreditorSaleDetail creditorSaleDetail) {
		DateTime currentDate = new DateTime();
		CreditorSaleDetail updateCreditorSaleDetail = new CreditorSaleDetail();
		updateCreditorSaleDetail.setId(creditorSaleDetail.getId());
		updateCreditorSaleDetail.setUserId(creditorSaleDetail.getUserId());
		updateCreditorSaleDetail.setBankSyncStatus((byte) 2);
		updateCreditorSaleDetail.setUpdateTime(currentDate.toDate());
		creditorSaleDetailMapperExt.updateByPrimaryKeyAndUserIdSelective(updateCreditorSaleDetail);
	}	
	
	public CreditorSaleOrderToLanMaoService getProxyObject() {
		return (CreditorSaleOrderToLanMaoService) AopContext.currentProxy();
	}
 }